package com.fredia.terp.util.oss;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectResult;
import com.fredia.terp.exception.ExceptionUtils;
import com.fredia.terp.util.SpringContextHolder;

/**
 * OSS 工具包
 * 
 * @author : wangyong
 * @since : 2017年6月27日
 * @version : v0.0.1
 */
public class OSSKit {

	private static Logger logger = Logger.getLogger(OSSKit.class);

	private static OSSObject ossObject;

	static {
		if (ossObject == null) {
			ossObject = SpringContextHolder.getBean(OSSObject.class);
		}
	}

	public static OSSObject getOSSObject() {
		if (ossObject == null) {
			ossObject = SpringContextHolder.getBean(OSSObject.class);
		}
		return ossObject;
	}

	/**
	 * 创建OSSClient
	 * 
	 * @return
	 * @author : wangyong
	 * @since : 2017年6月27日
	 */
	private static OSSClient openOSSClient() {
		/*
		 * // 创建ClientConfiguration实例 ClientConfiguration conf = new
		 * ClientConfiguration(); // 设置OSSClient使用的最大连接数，默认1024
		 * conf.setMaxConnections(200); // 设置请求超时时间，默认50秒
		 * conf.setSocketTimeout(10000); // 设置失败请求重试次数，默认3次
		 * conf.setMaxErrorRetry(5);
		 */
		OSSClient client = new OSSClient(ossObject.getEndpoint(), ossObject.getAccessKeyId(),
				ossObject.getAccessKeySecret());
		return client;
	}

	/**
	 * 关闭OSSClient
	 * 
	 * @param client
	 * @author : wangyong
	 * @since : 2017年6月27日
	 */
	public static void closeOSSClient(OSSClient client) {
		if (client != null) {
			client.shutdown();
		}
	}

	/**
	 * stream 流上传
	 * 
	 * 获取回调返回的消息体 getCallbackResponseBody()，需要close。
	 * 
	 * @param inputStream
	 * @param path
	 * @return
	 * @author : wangyong
	 * @since : 2017年6月27日
	 */
	public static PutObjectResult uploadStream(InputStream inputStream, String path) {
		if (inputStream == null || StringUtils.isBlank(path)) {
			ExceptionUtils.throwBaseException(" oss 上传请输入上传内容或路径...");
		}
		OSSClient ossClient = openOSSClient();
		PutObjectResult objectResult = null;
		// 上传流
		try {
			objectResult = ossClient.putObject(ossObject.getDefaultBucketName(), path, inputStream);
			// TODO 处理OSS 返回信息流 objectResult 获取回调返回的消息体
			// getCallbackResponseBody()，需要close。
		} catch (OSSException e) {
			e.printStackTrace();
			logger.error(e);
			ExceptionUtils.throwBaseException(" OSSException " + e.getMessage());
		} catch (ClientException e) {
			e.printStackTrace();
			logger.error(e);
			ExceptionUtils.throwBaseException(" ClientException " + e.getMessage());
		} finally {
			closeOSSClient(ossClient); // close
		}
		return objectResult;
	}

	/**
	 * 上传字符串
	 * 
	 * 获取回调返回的消息体 getCallbackResponseBody()，需要close。
	 * 
	 * @param str
	 * @param path
	 * @return
	 * @author : wangyong
	 * @since : 2017年6月27日
	 */
	public static PutObjectResult uploadStr(String str, String path) {
		if (StringUtils.isBlank(str) || StringUtils.isBlank(path)) {
			ExceptionUtils.throwBaseException(" oss 上传请输入上传内容或路径...");
		}
		OSSClient ossClient = openOSSClient();
		PutObjectResult objectResult = null;
		// 上传字符串
		try {
			objectResult = ossClient.putObject(ossObject.getDefaultBucketName(), path,
					new ByteArrayInputStream(str.getBytes()));
		} catch (OSSException e) {
			e.printStackTrace();
			logger.error(e);
			ExceptionUtils.throwBaseException(" OSSException " + e.getMessage());
		} catch (ClientException e) {
			e.printStackTrace();
			logger.error(e);
			ExceptionUtils.throwBaseException(" ClientException " + e.getMessage());
		} finally {
			closeOSSClient(ossClient); // close
		}
		return objectResult;
	}

	/**
	 * 上传 byte[] 数组
	 * 
	 * 获取回调返回的消息体 getCallbackResponseBody()，需要close。
	 * 
	 * @param bs
	 * @param path
	 * @return
	 * @author : wangyong
	 * @since : 2017年6月27日
	 */
	public static PutObjectResult uploadBytes(byte[] bs, String path) {
		if (StringUtils.isBlank(path) || bs.length <= 0) {
			ExceptionUtils.throwBaseException(" oss 上传请输入上传内容或路径...");
		}

		OSSClient ossClient = openOSSClient();
		PutObjectResult objectResult = null;
		try {
			// 上传字符串
			objectResult = ossClient.putObject(ossObject.getDefaultBucketName(), path, new ByteArrayInputStream(bs));
		} catch (OSSException e) {
			e.printStackTrace();
			logger.error(e);
			ExceptionUtils.throwBaseException(" OSSException " + e.getMessage());
		} catch (ClientException e) {
			e.printStackTrace();
			logger.error(e);
			ExceptionUtils.throwBaseException(" ClientException " + e.getMessage());
		} finally {
			closeOSSClient(ossClient); // close
		}
		return objectResult;
	}

	/**
	 * 上传网络流
	 * 
	 * 获取回调返回的消息体 getCallbackResponseBody()，需要close。
	 * 
	 * @param url
	 * @param path
	 * @return
	 * @author : wangyong
	 * @since : 2017年6月27日
	 */
	public static PutObjectResult uploadNetworkStream(String url, String path) {
		if (StringUtils.isBlank(path) || StringUtils.isBlank(url)) {
			ExceptionUtils.throwBaseException(" oss 上传请输入上传内容或路径...");
		}
		InputStream inputStream = null;
		PutObjectResult objectResult = null;
		OSSClient ossClient = openOSSClient();
		try {
			inputStream = new URL(url).openStream();
			// 上传字符串
			objectResult = ossClient.putObject(ossObject.getDefaultBucketName(), path, inputStream);
		} catch (MalformedURLException e) {
			e.printStackTrace();
			logger.error(e);
			ExceptionUtils.throwBaseException(e.getMessage());
		} catch (IOException e) {
			e.printStackTrace();
			logger.error(e);
			ExceptionUtils.throwBaseException(e.getMessage());
		} finally {
			closeOSSClient(ossClient); // close
			// close inputStream
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
					logger.error(e);
					ExceptionUtils.throwBaseException(" oss close inputStream " + e.getMessage());
				}
			}
		}
		return objectResult;
	}

	/**
	 * 上传文件流
	 * 
	 * 获取回调返回的消息体 getCallbackResponseBody()，需要close。
	 * 
	 * @param filePath
	 * @param path
	 * @return
	 * @author : wangyong
	 * @since : 2017年6月27日
	 */
	public static PutObjectResult uploadFileStream(String filePath, String path) {
		if (StringUtils.isBlank(path) || StringUtils.isBlank(filePath)) {
			ExceptionUtils.throwBaseException(" oss 上传请输入上传内容或路径...");
		}
		InputStream inputStream = null;
		PutObjectResult objectResult = null;
		OSSClient ossClient = openOSSClient();
		try {
			inputStream = new FileInputStream(filePath);
			// 上传字符串
			objectResult = ossClient.putObject(ossObject.getDefaultBucketName(), path, inputStream);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			logger.error(e);
			ExceptionUtils.throwBaseException(e.getMessage());
		} finally {
			closeOSSClient(ossClient); // close
			// close inputStream
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
					logger.error(e);
					ExceptionUtils.throwBaseException(" oss close inputStream " + e.getMessage());
				}
			}
		}
		return objectResult;
	}

	/**
	 * 上传文件
	 * 
	 * 获取回调返回的消息体 getCallbackResponseBody()，需要close。
	 * 
	 * @param file
	 * @param path
	 * @return
	 * @author : wangyong
	 * @since : 2017年6月27日
	 */
	public static PutObjectResult uploadFile(String file, String path) {
		if (StringUtils.isBlank(path) || StringUtils.isBlank(file)) {
			ExceptionUtils.throwBaseException(" oss 上传请输入上传内容或路径...");
		}
		PutObjectResult objectResult = null;
		OSSClient ossClient = openOSSClient();
		try {
			// 上传文件
			objectResult = ossClient.putObject(ossObject.getDefaultBucketName(), path, new File(file));
		} catch (OSSException e) {
			e.printStackTrace();
			logger.error(e);
			ExceptionUtils.throwBaseException(" OSSException " + e.getMessage());
		} catch (ClientException e) {
			e.printStackTrace();
			logger.error(e);
			ExceptionUtils.throwBaseException(" ClientException " + e.getMessage());
		} finally {
			ossClient.shutdown();
		}
		return objectResult;
	}

	/**
	 * 删除单个 OSS 存储对象
	 * 
	 * @param bucketName
	 * @param path
	 * @author : wangyong
	 * @since : 2017年6月27日
	 */
	public static void deleteObject(String bucketName, String path) {
		if (StringUtils.isEmpty(path)) {
			ExceptionUtils.throwBaseException("请输入删除对象路径...");
		}

		String bName = null;
		OSSClient ossClient = openOSSClient();
		if (bucketName != null) {
			bName = bucketName;
		} else {
			bName = ossObject.getDefaultBucketName();
		}

		try {
			ossClient.deleteObject(bName, path);
		} catch (OSSException e) {
			e.printStackTrace();
			ExceptionUtils.throwBaseException("deleteObject OSSException " + e.getMessage());
		} catch (ClientException e) {
			e.printStackTrace();
			ExceptionUtils.throwBaseException("deleteObject ClientException " + e.getMessage());
		}
	}

}
